use core::fmt;
use std::{
    fs::{self, File},
    io::Write,
    path::Path,
};

use log::info;

use crate::cliargs::TranslateRule;

/// 时间戳
#[derive(Debug)]
pub struct Timestamp {
    hours: u8,
    minutes: u8,
    seconds: u8,
    milliseconds: u16,
}
impl Timestamp {
    fn new(hours: u8, minutes: u8, seconds: u8, milliseconds: u16) -> Timestamp {
        Timestamp {
            hours,
            minutes,
            seconds,
            milliseconds,
        }
    }
    fn parse(t: i64) -> Self {
        let msec = t * 10;
        let hr = msec / (1000 * 60 * 60);
        let msec = msec - hr * (1000 * 60 * 60);
        let min = msec / (1000 * 60);
        let msec = msec - min * (1000 * 60);
        let sec = msec / 1000;
        let msec = msec - sec * 1000;
        Timestamp {
            hours: hr as u8,
            minutes: min as u8,
            seconds: sec as u8,
            milliseconds: msec as u16,
        }
    }

    fn parse_str(str: &str) -> Self {
        let times: Vec<&str> = str.split(",").collect();
        let ms = times.get(1).unwrap().parse().unwrap();
        let times_strs: Vec<&str> = times.first().unwrap().split(":").collect();
        let h: u8 = times_strs.first().unwrap().parse().unwrap();
        let min = times_strs.get(1).unwrap().parse().unwrap();
        let s = times_strs.get(2).unwrap().parse().unwrap();
        Timestamp::new(h, min, s, ms)
    }
}

impl fmt::Display for Timestamp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{:02}:{:02}:{:02},{:03}",
            self.hours, self.minutes, self.seconds, self.milliseconds
        )
    }
}

/// 单条字幕结构体
#[derive(Debug)]
pub struct SubTitle {
    num: u32,
    start_time: Timestamp,
    end_time: Timestamp,
    pub content: String,
}
impl SubTitle {
    /// 根据参数构造单条字幕
    fn new(num: u32, start_time: Timestamp, end_time: Timestamp, content: String) -> SubTitle {
        SubTitle {
            num,
            start_time,
            end_time,
            content,
        }
    }
    /// 添加翻译，即修改字幕内的文本。
    pub fn add_translate(&mut self, translate: String, trans_rule: &TranslateRule) {
        match trans_rule {
            TranslateRule::TranslateDown => {
                self.content = format!("{}\n{}", self.content, translate);
            }
            TranslateRule::TranslateUp => {
                self.content = format!("{}\n{}", translate, self.content);
            }
            TranslateRule::TranslateOnly => {
                self.content = translate.to_string();
            }
        }
    }
}
/// 字幕
#[derive(Debug)]
pub struct SubTitles(Vec<SubTitle>);
impl Default for SubTitles {
    ///生成一个空的字幕
    fn default() -> Self {
        Self(Default::default())
    }
}
impl SubTitles {
    ///从指定的文件加载字幕
    pub fn load_from_file(path: &Path) -> Self {
        assert!(path.exists());
        let mut subtitles = vec![];
        match fs::read_to_string(path) {
            Err(err) => panic!("read file error:{}", err),
            Ok(file_contents) => {
                let mut content_iter = file_contents.lines();
                loop {
                    let mut start_time = Timestamp::new(0, 0, 0, 0);
                    let mut end_time = Timestamp::new(0, 0, 0, 0);
                    let mut content = String::new();
                    if let Some(line_str) = content_iter.next() {
                        //find the first num line
                        if line_str.parse::<u32>().is_ok() {
                            let num = line_str.parse().unwrap();
                            if let Some(line_time_str) = content_iter.next() {
                                let times: Vec<&str> = line_time_str.split(" --> ").collect();
                                if times.len() == 2 {
                                    start_time = Timestamp::parse_str(times[0]);
                                    end_time = Timestamp::parse_str(times[1]);
                                }
                            }

                            for line_content in content_iter.by_ref() {
                                if !line_content.is_empty() {
                                    content.push_str(line_content);
                                } else {
                                    break;
                                }
                            }
                            subtitles.push(SubTitle::new(
                                num,
                                start_time,
                                end_time,
                                content.clone(),
                            ));
                            content.clear();
                        }
                    } else {
                        break;
                    }
                }
                SubTitles(subtitles)
            }
        }
    }
    /// 添加一条字幕
    pub fn add(&mut self, num: u32, start_time: i64, end_time: i64, content: String) {
        let start_time = Timestamp::parse(start_time);
        let end_time = Timestamp::parse(end_time);
        let subtitle = SubTitle::new(num, start_time, end_time, content);
        self.0.push(subtitle);
    }
    fn _add_subtitles(&mut self, subtitle: SubTitle) {
        self.0.push(subtitle);
    }
    fn _get(&self, index: usize) -> Option<&SubTitle> {
        self.0.get(index)
    }
    fn _len(&self) -> usize {
        self.0.len()
    }
    /// 将字幕保存到指定文件
    /// 如果是windows系统，则使用utf8-bom编码；linux系统则使用utf8编码
    pub fn write_to_file(&self, file_path: &str) {
        info!("start write_to_file...");
        let mut file = File::create(file_path).unwrap();
        //兼容windows 使用utf-8 bom格式
        if cfg!(target_os = "windows") {
            file.write_all(b"\xEF\xBB\xBF").unwrap();
        }

        for subtitle in self.0.iter() {
            let line = format!(
                "{}\n{} --> {}\n{}\n\n",
                subtitle.num, subtitle.start_time, subtitle.end_time, subtitle.content
            );
            file.write_all(line.as_bytes()).unwrap();
        }
        file.flush().unwrap();
    }
}

impl<'a> IntoIterator for &'a mut SubTitles {
    type Item = &'a mut SubTitle;
    type IntoIter = std::slice::IterMut<'a, SubTitle>;
    fn into_iter(self) -> Self::IntoIter {
        self.0.iter_mut()
    }
}
